using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using SharpCompress.Readers;
using WebUpdaterAdminCore.Data;
using WebUpdaterAdminCore.Models;

// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

namespace WebUpdaterAdminCore.WebApi
{
    [Route("api/[controller]")]
    public class FileManagerController : Controller
    {
        private const string _uploadPathName = "FileUploads";
        private ILogger<FileManagerController> _logger;
        private ApplicationDbContext _dbContext;
        //private UpdaterSocketServerService _socketServerService;
        private readonly IHostingEnvironment _hostingEnvironment;
        public FileManagerController(ApplicationDbContext dbContext,
            ILogger<FileManagerController> logger,
            IHostingEnvironment hostingEnv)
        {
            _dbContext = dbContext;
            _logger = logger;
            _hostingEnvironment = hostingEnv;
        }

      
        [HttpPost("[action]")]
        public async Task<IActionResult> UploadFile()
        {
            string siteName = Request.Form["siteName"];
            string siteId = Request.Form["siteId"];
            string versionFileName = Request.Form["versionFileName"];
            if (string.IsNullOrEmpty(siteName))
            {
                return Json(new ErrorResult(100101, "参数siteName不能为空"));
            }
            var uploadPath = Path.Combine(_hostingEnvironment.ContentRootPath, _uploadPathName);
            if (!Directory.Exists(uploadPath))
            {
                Directory.CreateDirectory(uploadPath);
            }
            UploadResultViewModel resultModel = null;
            if (!string.IsNullOrEmpty(siteName))
            {
                var files = Request.Form.Files;
                foreach (var f in files)
                {
                    using (var stream = f.OpenReadStream())
                    {
                        var fileMd5 = Utils.Common.FileMd5(stream);
                        var fileName = f.FileName;
                        var fileExt = Path.GetExtension(fileName);
                        var newFileName = fileMd5 + fileExt;
                        var uploadFileName = Path.Combine( uploadPath ,newFileName);
                       
                        if (System.IO.File.Exists(uploadFileName))
                        {
                            System.IO.File.Delete(uploadFileName);
                        }
                        using (var fStream = new FileStream(uploadFileName, FileMode.Create))
                        {
                            await f.CopyToAsync(fStream);
                        }
                        //获取文件版本号
                        var version = GetFileVersion(uploadFileName, versionFileName);
                        if (string.IsNullOrEmpty(version))
                        {
                            System.IO.File.Delete(uploadFileName);
                            return Json(new ErrorResult(100216, $"上传失败，原因：名称为【{versionFileName}】在上传文件包中不存在"));
                        }
                        var fileupInfo = _dbContext.FileUploadInfos.Find(fileMd5);
                        if(fileupInfo != null)
                        {
                            fileupInfo.FileName = fileName;
                            fileupInfo.FilePath = uploadFileName;
                            fileupInfo.FileSize = f.Length;
                            fileupInfo.SiteName = siteName;
                            fileupInfo.FileVersion = version;
                            _dbContext.FileUploadInfos.Update(fileupInfo);
                        }
                        else
                        {
                            _dbContext.FileUploadInfos.Add(new FileUploadInfo
                            {
                                Id = fileMd5,
                                FileName = fileName,
                                FilePath = uploadFileName,
                                FileSize = f.Length,
                                FileVersion = version,
                                SiteName = siteName
                            });
                        }
                        await _dbContext.SaveChangesAsync();

                        
                        resultModel = new UploadResultViewModel(siteId, GetDownlink(newFileName), fileMd5, version);
                    }
                }
            }            
            else
            {
                return Json(new ErrorResult(100100, "参数type输入错误"));
            }
            if(resultModel != null)
            {
                return Json(resultModel);
            }
            else
            {
                return Json(new ErrorResult(100216, "上传失败"));
            }

        }

        /// <summary>
        /// 获取文件版本号
        /// </summary>
        /// <param name="filePath">压缩包文件路径</param>
        /// <param name="assemblyFileName">决定版本号的文件名称</param>
        /// <returns></returns>
        private string GetFileVersion(string filePath,string assemblyFileName)
        {
            if (string.IsNullOrEmpty(assemblyFileName))
            {
                throw new ArgumentNullException($"assemblyFileName参数不能为空");
            }
            if (!System.IO.File.Exists(filePath))
            {
                throw new FileNotFoundException($"{filePath}文件不存在");
            }
            var fileVersion = "";
            try
            {
                var tmpFileName = System.IO.Path.GetTempFileName();

                using (Stream stream = System.IO.File.OpenRead(filePath))
                using (var reader = ReaderFactory.Open(stream))
                {
                    while (reader.MoveToNextEntry())
                    {
                        if (!reader.Entry.IsDirectory)
                        {
                            var fileName = reader.Entry.Key;
                            if (string.IsNullOrEmpty(fileName))
                            {
                                continue;
                            }
                            if (fileName.IndexOf(assemblyFileName) > -1)
                            {
                                reader.WriteEntryToFile(tmpFileName, new ExtractionOptions() { Overwrite = true });
                                break;
                            }
                        }
                    }
                    //检测文件版本号
                    var assemblyName = AssemblyName.GetAssemblyName(tmpFileName);
                    if(assemblyName == null)
                    {
                        fileVersion = "";
                    }
                    else
                    {
                        fileVersion = assemblyName.Version.ToString();
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取版本号出错，zip包文件：{0}，检测版本文件：{1}", filePath, assemblyFileName);
            }
            return fileVersion;
        }

        private string GetDownlink(string fileName)
        {
            var url =  $"{Request.Scheme}://{Request.Host.Value}/{_uploadPathName}/{fileName}";
            return url;
        }
    }
}
